home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagd_f.zip / FILES.SWG / 0054_Buffered Fileread.pas < prev    next >
Pascal/Delphi Source File  |  1994-05-26  |  8KB  |  272 lines

  1.  
  2. (************************************************************************)
  3. (*                                                                      *)
  4. (*  Program ex. to      : "Tips & Tricks in Turbo Pascal", SysTime 1993 *)
  5. (*                                                                      *)
  6. (*  By                  : Martin Israelsen                              *)
  7. (*                                                                      *)
  8. (*  Title               : BUFFER.PAS                                    *)
  9. (*                                                                      *)
  10. (*  Chapter             : 5                                             *)
  11. (*                                                                      *)
  12. (*  Description         : Quicker than Turbo fileread                   *)
  13. (*                                                                      *)
  14. (************************************************************************)
  15. (*$I-*)  (* Iocheck off         *)
  16. (*$F+*)  (* Force FAR call      *)
  17. (*$V-*)  (* Relaxed VAR check   *)
  18. (*$R-*)  (* Range check off     *)
  19. (*$S-*)  (* Stack check off     *)
  20. (*$Q-*)  (* Overflow off        *)
  21. (*$D-*)  (* Debug off           *)
  22. (*$L-*)  (* Linenumber off      *)
  23.  
  24. Unit
  25.   Buffer;
  26.  
  27. Interface
  28.  
  29. Type
  30.  
  31.   PByte     = ^Byte;
  32.   PWord     = ^Word;
  33.   PLong     = ^Longint;
  34.  
  35.   PByteArr  = ^TByteArr;
  36.   TByteArr  = Array[1..64000] Of Byte;
  37.   PfStr     = String[100];
  38.  
  39.   PBuffer       = ^TBuffer;
  40.   TBuffer       = Record
  41.                      BufFil   : File;
  42.                      BufPtr   : PByteArr;
  43.  
  44.                      BufSize,
  45.                      BufIndex,
  46.                      BufUsed  : Word;
  47.  
  48.                      BufFPos,
  49.                      BufFSize : Longint;
  50.                   End;
  51.  
  52. Function  BufferInit(Var Br: PBuffer; MemSize: Word;
  53.                       FilName: PfStr): Boolean;
  54. Procedure BufferClose(Var Br: PBuffer);
  55.  
  56. Function  BufferGetByte(Br: PBuffer): Byte;
  57. Function  BufferGetByteAsm(Br: PBuffer): Byte;
  58.  
  59. Function  BufferGetWord(Br: PBuffer): Word;
  60. Procedure BufferGetBlock(Br: PBuffer; Var ToAdr; BlockSize: Word);
  61. Function  BufferGetStringAsm(Br: PBuffer): String;
  62.  
  63. Function  BufferEof(Br: PBuffer): Boolean;
  64.  
  65. Implementation
  66.  
  67. (*$I-,F+*)
  68.  
  69. Function BufferInit(Var Br: PBuffer; MemSize: Word;
  70.                     FilName: PfStr): Boolean;
  71. Begin
  72.    BufferInit:=False;
  73.  
  74.    (* Check if there's enough memory               *)
  75.  
  76.    If MemSize<500 Then Exit;
  77.    If MaxAvail<Sizeof(TBuffer)+MemSize+32 Then Exit;
  78.  
  79.    New(Br);
  80.  
  81.    With BR^ Do
  82.    Begin
  83.       BufSize:=MemSize; BufIndex:=1; BufFPos:=0;
  84.  
  85.       (* Open the filen. Exit if there's an error *)
  86.  
  87.       Assign(BufFil,Filname); Reset(BufFil,1);
  88.  
  89.       If IoResult<>0 Then
  90.       Begin
  91.          Dispose(Br);
  92.          Exit;
  93.       End;
  94.  
  95.       (* Ok, the file is there, and there's enough *)
  96.       (* memory. So allocate the memory and read   *)
  97.       (* as much as possible                       *)
  98.  
  99.       GetMem(BufPtr,BufSize);
  100.       BlockRead(BufFil,BufPtr^,BufSize,BufUsed);
  101.  
  102.       BufFSize:=FileSize(BufFil); Inc(BufFPos,BufUsed);
  103.    End;
  104.  
  105.    BufferInit:=True;
  106. End;
  107.  
  108. Procedure BufferClose(Var Br: PBuffer);
  109. Begin
  110.    With Br^ Do
  111.    Begin
  112.       Close(BufFil);
  113.       Freemem(BufPtr,BufSize);
  114.    End;
  115.  
  116.    Dispose(Br);
  117. End;
  118.  
  119. Procedure BufferCheck(Br: PBuffer; ReqBytes: Word);
  120. Var
  121.    W,Rest: Word;
  122. Begin
  123.    With Br^ Do
  124.    Begin
  125.       If (BufIndex+ReqBytes>BufUsed) And (BufUsed=BufSize) Then
  126.       Begin
  127.          Rest:=Succ(BufSize-BufIndex);
  128.  
  129.          Move(BufPtr^[BufIndex],BufPtr^[1],Rest);
  130.          BufIndex:=1;
  131.  
  132.          BlockRead(BufFil,BufPtr^[Succ(Rest)],BufSize-Rest,W);
  133.          BufUsed:=Rest+W; Inc(BufFPos,W);
  134.       End;
  135.    End;
  136. End;
  137.  
  138. Function BufferGetByte(Br: PBuffer): Byte;
  139. Begin
  140.    With Br^ Do
  141.    Begin
  142.       BufferCheck(Br,1);
  143.  
  144.       BufferGetByte:=BufPtr^[BufIndex];
  145.       Inc(BufIndex);
  146.    End;
  147. End;
  148.  
  149. Function BufferGetByteAsm(Br: PBuffer): Byte; Assembler;
  150. Asm
  151.    Les   Di,Br                              (* ES:DI ->  BRecPtr         *)
  152.  
  153.    Mov   Ax,Es:[Di.TBuffer.BufIndex]        (* Check wheather the buffer should be updated *)
  154.    Cmp   Ax,Es:[Di.TBuffer.BufUsed]
  155.    Jle   @@NoBufCheck                       (* If not jump on            *)
  156.  
  157.    Push  Word Ptr Br[2]                     (* Push BR to BufferCheck   *)
  158.    Push  Word Ptr Br
  159.    Mov   Ax,0001                            (* Check for one byte           *)
  160.    Push  Ax                                 (* Push it                      *)
  161.    Push  CS                                 (* Push CS, and make a          *)
  162.    Call  Near Ptr BufferCheck               (* NEAR call - it's quicker     *)
  163.  
  164.    Les   Di,Br                              (* ES:DI-> BRecPtr              *)
  165.  
  166.  @@NoBufCheck:
  167.  
  168.    Mov   Bx,Es:[Di.TBuffer.BufIndex]        (* BufferIndex in BX            *)
  169.    Inc   Es:[Di.TBuffer.BufIndex]           (* Inc BufferIndex directly     *)
  170.    Les   Di,Es:[Di.TBuffer.BufPtr]          (* ES:DI -> BufPtr              *)
  171.  
  172.    Xor   Ax,Ax                              (* Now get the byte             *)
  173.    Mov   Al,Byte Ptr Es:[Di+Bx-1]
  174. End;
  175.  
  176. Function BufferGetWord(Br: PBuffer): Word;
  177. Begin
  178.    With Br^ Do
  179.    Begin
  180.       BufferCheck(Br,2);
  181.  
  182.       BufferGetWord:=PWord(@BufPtr^[BufIndex])^;
  183.       Inc(BufIndex,2);
  184.    End;
  185. End;
  186.  
  187. Procedure BufferGetBlock(Br: PBuffer; Var ToAdr; BlockSize: Word);
  188. Begin
  189.    With Br^ Do
  190.    Begin
  191.       BufferCheck(Br,BlockSize);
  192.  
  193.       Move(BufPtr^[BufIndex],ToAdr,BlockSize);
  194.       Inc(BufIndex,BlockSize);
  195.    End;
  196. End;
  197.  
  198. Function BufferGetStringAsm(Br: PBuffer): String; Assembler;
  199. Asm
  200.    Push   Ds
  201.  
  202.    Les    Di,Br                        (* es:di -> Br *)
  203.    Mov    Bx,Es:[Di.TBuffer.BufUsed]   (* check for buffercheck *)
  204.    Sub    Bx,Es:[Di.TBuffer.BufIndex]
  205.    Cmp    Bx,257
  206.    Jae    @NoBufCheck                  (* Jump on if not        *)
  207.  
  208.    Push   Word Ptr Br[2]
  209.    Push   Word Ptr Br
  210.  
  211.    Mov    Ax,257
  212.    Push   Ax
  213.  
  214.    Push   Cs
  215.    Call   Near Ptr BufferCheck
  216.  
  217.    Les    Di,Br
  218.  
  219.  @NoBufCheck:
  220.  
  221.    Mov    Bx,Es:[Di.TBuffer.BufIndex]  (* Get index in buffer     *)
  222.    Dec    Bx                           (* Adjust for 0            *)
  223.  
  224.    Les    Di,Es:[Di.TBuffer.BufPtr]    (* Point to the buffer     *)
  225.    Add    Di,Bx                        (* Add Index               *)
  226.    Push   Di                           (* Save currect position   *)
  227.  
  228.    Mov    Al,$0a                       (* Search for CR = 0ah     *)
  229.    Mov    Cx,$ff                       (* max. 255 chars          *)
  230.  
  231.    Cld                                 (* Remember                *)
  232.    RepNz  Scasb                        (* and do the search       *)
  233.    Jz     @Fundet                      (* Jump if we found one    *)
  234.  
  235.    Mov    Cx,0                         (* Otherwise set length to 0  *)
  236.  @Fundet:
  237.    Sub    Cx,$ff                       (* Which will be recalculated *)
  238.    Neg    Cx                           (* to nomal length            *)
  239.    Dec    Cx                           (* Dec, to avoid CR           *)
  240.  
  241.    Push   Es                           (* DS:SI->Buffer              *)
  242.    Pop    Ds
  243.    Pop    Si
  244.  
  245.    Les    Di,@Result                   (* ES:DI->result string        *)
  246.    Mov    Ax,Cx
  247.  
  248.    Stosb                               (* Set length                  *)
  249.  
  250.    Shr    Cx,1                         (* Copy the string             *)
  251.    Rep    MovSw
  252.    Adc    Cx,Cx
  253.    Rep    MovSb
  254.  
  255.    Pop    Ds                           (* Restore DS                  *)
  256.  
  257.    Les    Di,Br                        (* ES:DI->Br                   *)
  258.    Inc    Ax                           (* Inc Ax, point to LF         *)
  259.  
  260.    Add    Es:[Di.TBuffer.BufIndex],Ax  (* and set BufferIndex         *)
  261. End;
  262.  
  263.  
  264. Function BufferEof(Br: PBuffer): Boolean;
  265. Begin
  266.    With Br^ Do
  267.    BufferEof:=(BufIndex>BufUsed) And (BufFPos=BufFSize);
  268. End;
  269.  
  270. End.
  271.  
  272.